use async_trait::async_trait;
use reqwest::{Client, Url};
use std::sync::Arc;
use std::time::Duration;
use std::path::{Path, PathBuf};
use futures_util::StreamExt;
use tokio::fs::{self, File};
use tokio::io::{AsyncReadExt, AsyncWriteExt, BufWriter};

// 项目内部模块
use crate::converter::{ConverterFactory};
use crate::config::DownloadConfig;
use crate::error::{DownloadError, DownloadResult};
use crate::format::{FormatDetector};
use crate::playlist::{Playlist, Segment, PlaylistFactory};
use crate::progress::{DualProgressReporter, ProgressReporter, SegmentStatus};
use crate::retry::RetryStrategy;
use crate::utils::ensure_dir_exists;
use crate::content_detector::ContentDetector;

/// 从URL路径中移除文件名，只保留目录路径
fn url_path_without_filename(path: &str) -> String {
    if let Some(last_slash) = path.rfind('/') {
        path[..last_slash + 1].to_string()
    } else {
        "/".to_string()
    }
}

/// 下载参数结构体
struct DownloadAttemptParams<'a> {
    client: &'a Client,
    filepath: &'a Path,
    url: &'a str,
    buffer_size: usize,
    segment_id: usize,
    progress_reporter: Arc<dyn DualProgressReporter>,
    progress_bar_created: &'a mut bool,
    progress_icon: &'a str,
}

/// 下载器接口
#[async_trait]
pub trait Downloader: Send + Sync {
    /// 下载单个 URL
    async fn download(&self, url: &str, output_path: &str) -> DownloadResult<()>;
    
    /// 下载播放列表
    async fn download_playlist(&self, url: &str) -> DownloadResult<Box<dyn Playlist<SegmentType = crate::playlist::M3u8Segment>>>;
    
    /// 清理临时文件
    async fn cleanup(&self) -> DownloadResult<()>;
}

/// HTTP 下载器实现（使用双层进度条）
pub struct DualProgressHttpDownloader {
    client: Client,
    config: DownloadConfig,
    progress_reporter: Arc<dyn DualProgressReporter>,
    retry_strategy: RetryStrategy,
}

impl DualProgressHttpDownloader {
    pub fn new(
        config: DownloadConfig,
        progress_reporter: Arc<dyn DualProgressReporter>,
        retry_strategy: RetryStrategy,
    ) -> DownloadResult<Self> {
        let client = Self::create_http_client(&config)?;
        
        if let Some(ref proxy) = config.proxy_url {
            println!("🔴 已启用 SOCKS5 代理: {proxy}");
        }
        
        Ok(Self {
            client,
            config,
            progress_reporter,
            retry_strategy,
        })
    }
    
    fn create_http_client(config: &DownloadConfig) -> DownloadResult<Client> {
        let mut client_builder = Client::builder()
            .timeout(Duration::from_secs(config.timeout_secs));
        
        // 如果提供了代理地址，则配置代理
        if let Some(ref proxy) = config.proxy_url {
            let proxy_config = reqwest::Proxy::all(proxy)
                .map_err(|e| DownloadError::Network(e.to_string()))?;
            client_builder = client_builder.proxy(proxy_config);
        }
        
        client_builder
            .build()
            .map_err(|e| DownloadError::Network(e.to_string()))
    }
    
    /// 下载单个分片（带进度报告）
    async fn download_segment_with_progress(
        client: &Client,
        retry_strategy: &RetryStrategy,
        temp_dir: &Path,
        buffer_size: usize,
        segment: &crate::playlist::M3u8Segment,
        progress_reporter: Arc<dyn DualProgressReporter>,
    ) -> DownloadResult<PathBuf> {
        let segment_id = segment.index();
        let detector = FormatDetector::new();
        let format = detector.detect_format(segment.url()).unwrap_or_else(|| detector.default_format());
        let filename = format.generate_filename(segment_id);
        let filepath = temp_dir.join(&filename);
        
        // 如果文件已存在，直接返回
        if filepath.exists() {
            return Ok(filepath);
        }
        
        let url = segment.url();
        let filepath_clone = filepath.clone();
        
        let mut retry_count = 0;
        let max_retries = retry_strategy.max_retries();
        let mut progress_bar_created = false; // 标记进度条是否已创建
        
        loop {
            match Self::download_segment_attempt(DownloadAttemptParams {
                client,
                filepath: &filepath_clone,
                url,
                buffer_size,
                segment_id,
                progress_reporter: Arc::clone(&progress_reporter),
                progress_bar_created: &mut progress_bar_created,
                progress_icon: segment.progress_icon(),
            }).await {
                Ok(_) => {
                    // 下载成功
                    if progress_bar_created {
                        progress_reporter.set_segment_status(
                            segment_id, 
                            SegmentStatus::Success, 
                            "下载完成",
                            segment.progress_icon()
                        ).await;
                        progress_reporter.finish_segment(segment_id, true).await;
                    }
                    return Ok(filepath);
                }
                Err(e) => {
                    retry_count += 1;
                    if retry_count <= max_retries {
                        // 首次失败时才创建进度条（如果还没创建）
                        if !progress_bar_created {
                            progress_reporter.start_segment_progress(segment_id, url, segment.progress_icon()).await;
                            progress_bar_created = true;
                        }
                        
                        println!("⚠️ 分片 {} 下载失败（第{}次尝试），准备重试 {}/{}: {}", 
                            segment_id, retry_count, retry_count, max_retries, e);
                        
                        // 标记为重试状态
                        progress_reporter.set_segment_status(
                            segment_id,
                            SegmentStatus::Retrying,
                            &format!("重试 {retry_count}/{max_retries}"),
                            segment.progress_icon()
                        ).await;
                        
                        // 等待重试间隔
                        if let Some(delay) = retry_strategy.retry_delay(retry_count - 1) {
                            println!("⏱️ 分片 {} 等待 {:?} 后重试", segment_id, delay);
                            tokio::time::sleep(delay).await;
                        }
                        println!("🔄 分片 {} 开始第{}次重试", segment_id, retry_count + 1);
                    } else {
                        // 重试次数用尽，标记为错误
                        println!("❌ 分片 {} 经过 {} 次重试后仍然失败: {}", segment_id, max_retries, e);
                        if !progress_bar_created {
                            progress_reporter.start_segment_progress(segment_id, url, segment.progress_icon()).await;
                        }
                        progress_reporter.set_segment_status(
                            segment_id,
                            SegmentStatus::Error,
                            "下载失败",
                            segment.progress_icon()
                        ).await;
                        progress_reporter.finish_segment(segment_id, false).await;
                        return Err(e);
                    }
                }
            }
        }
    }
    
    /// 单次下载尝试
    async fn download_segment_attempt(params: DownloadAttemptParams<'_>) -> DownloadResult<()> {
        let DownloadAttemptParams {
            client,
            filepath,
            url,
            buffer_size,
            segment_id,
            progress_reporter,
            progress_bar_created,
            progress_icon,
        } = params;
        
        let response = client.get(url).send().await?;
        
        // 网络连接成功，现在才创建进度条显示
        if !*progress_bar_created {
            progress_reporter.start_segment_progress(segment_id, url, progress_icon).await;
            *progress_bar_created = true;
        }
        
        // 检查 HTTP 状态码
        if !response.status().is_success() {
            return Err(DownloadError::Network(format!("HTTP 错误: {}", response.status())));
        }
        
        let content_length = response.content_length().unwrap_or(0);
        let mut stream = response.bytes_stream();
        let file = File::create(filepath).await?;
        let mut writer = BufWriter::with_capacity(buffer_size, file);
        let mut downloaded = 0u64;
        let mut _first_chunk = true;
        
        // 更新分片进度条总大小
        if content_length > 0 {
            progress_reporter.update_segment_progress(segment_id, 0, content_length).await;
        }
        
        // 零拷贝流式下载
        while let Some(chunk_result) = stream.next().await {
            let chunk = chunk_result?;
            
            // 检测第一个数据块的真实格式
            if _first_chunk && chunk.len() >= 8 {
                let real_format = ContentDetector::detect_real_format(&chunk);
                let filename_ext = filepath.extension()
                    .and_then(|ext| ext.to_str())
                    .unwrap_or("unknown");
                
                // 当检测到格式为"unknown"时，默认使用"ts"格式
                let effective_format = if real_format == "unknown" { "ts" } else { real_format };
                let _analysis = ContentDetector::analyze_format_mismatch(filename_ext, effective_format);
                
                // 如果格式不匹配，输出警告信息
                if filename_ext != effective_format {
                    // 移除了格式检测的详细输出，只保留进度条更新
                    // println!("📊 格式检测结果 (分片 {segment_id}): {analysis}");
                    // println!("   文件: {} -> 实际内容: {} ({})", 
                    //     filename_ext.to_uppercase(), 
                    //     effective_format.to_uppercase(),
                    //     ContentDetector::get_format_description(effective_format)
                    // );
                }
                
                _first_chunk = false;
            }
            
            writer.write_all(&chunk).await?;
            downloaded += chunk.len() as u64;
            
            // 更新分片进度
            if content_length > 0 {
                progress_reporter.update_segment_progress(segment_id, downloaded, content_length).await;
            }
        }
        
        writer.flush().await?;
        
        // 验证文件大小（简单检查）
        let metadata = fs::metadata(filepath).await?;
        if metadata.len() == 0 {
            fs::remove_file(filepath).await.ok(); // 删除空文件
            return Err(DownloadError::Io("下载的文件为空".to_string()));
        }
        
        Ok(())
    }
    
    /// 并发下载所有分片（使用双层进度条和真正的流水线并发）
    async fn download_all_segments(&self, playlist: &dyn Playlist<SegmentType = crate::playlist::M3u8Segment>) -> DownloadResult<Vec<PathBuf>> {
        ensure_dir_exists(&self.config.temp_dir).await?;
        
        let segments = playlist.segments();
        let total = segments.len();
        
        // 更新固定显示信息为下载分片
        self.progress_reporter.set_current_download(
            &format!("{total} 个视频分片"), 
            "开始流水线并发下载"
        ).await;
        
        // 启动总进度条
        self.progress_reporter.start_total_progress(total as u64, "下载视频分片").await;
        
        // 将segments转换为有所有权的集合，避免生命周期问题
        let segments_owned: Vec<_> = segments.iter().cloned().collect();
        
        // 使用真正的工作队列模式进行流水线并发
        let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
        let segment_queue = Arc::new(tokio::sync::Mutex::new(segments_owned.into_iter().enumerate()));
        let results = Arc::new(tokio::sync::Mutex::new(Vec::with_capacity(total)));
        let failed_segments = Arc::new(tokio::sync::Mutex::new(Vec::new()));
        
        // 启动工作协程池 - 每个协程独立工作，完成一个任务立即获取下一个
        let mut worker_handles = Vec::new();
        for worker_id in 0..self.config.concurrent {
            let client = self.client.clone();
            let retry_strategy = self.retry_strategy.clone();
            let temp_dir = self.config.temp_dir.clone();
            let buffer_size = self.config.buffer_size;
            let progress_reporter = Arc::clone(&self.progress_reporter);
            let segment_queue = Arc::clone(&segment_queue);
            let results = Arc::clone(&results);
            let failed_segments = Arc::clone(&failed_segments);
            let tx = tx.clone();
            
            let handle = tokio::spawn(async move {
                let mut _task_count = 0;
                
                loop {
                    // 从队列中获取下一个任务
                    let task = {
                        let mut queue = segment_queue.lock().await;
                        queue.next()
                    };
                    
                    match task {
                        Some((index, segment)) => {
                            _task_count += 1;
                            // 移除了协程获取任务的输出
                            // println!("📥 协程 {} 获取任务: 分片 {} (协程已处理 {} 个任务)", 
                            //     worker_id + 1, index, task_count);
                            
                            // 立即开始下载这个分片 - 不等待其他协程
                            let result = Self::download_segment_with_progress(
                                &client, 
                                &retry_strategy, 
                                &temp_dir, 
                                buffer_size, 
                                &segment,
                                Arc::from(progress_reporter.clone_reporter())
                            ).await;
                            
                            // 更新总进度
                            progress_reporter.increment_total(1).await;
                            
                            // 保存结果
                            match result {
                                Ok(filepath) => {
                                    let mut results_guard = results.lock().await;
                                    results_guard.push((index, filepath));
                                }
                                Err(e) => {
                                    let mut failed_guard = failed_segments.lock().await;
                                    failed_guard.push((segment.clone(), e.clone()));
                                    println!("❌ 协程 {} 分片 {} 经过所有重试后仍然失败: {}", worker_id + 1, index, e);
                                }
                            }
                            
                            // 通知有任务完成
                            let _ = tx.send(());
                        }
                        None => {
                            // 没有更多任务，工作协程退出
                            break;
                        }
                    }
                }
            });
            
            worker_handles.push(handle);
        }
        
        // 关闭发送端，这样接收端知道不会再有新消息
        drop(tx);
        
        // 等待所有任务完成
        let mut completed_tasks = 0;
        while completed_tasks < total {
            if rx.recv().await.is_some() {
                completed_tasks += 1;
            } else {
                // 通道关闭，检查是否所有工作协程都完成了
                break;
            }
        }
        
        // 等待所有工作协程完成
        for handle in worker_handles {
            let _ = handle.await;
        }
        
        // 收集结果
        let results_guard = results.lock().await;
        let failed_guard = failed_segments.lock().await;
        
        // 检查是否有失败的下载
        if !failed_guard.is_empty() {
            let failed_count = failed_guard.len();
            self.progress_reporter.finish_total("❌ 部分文件下载失败").await;
            
            eprintln!();
            eprintln!("❌ 以下 {} 个 TS 文件经过 {} 次重试后仍然失败：", failed_count, self.config.retry_count);
            for (segment, error) in failed_guard.iter() {
                eprintln!("  - 索引 {}: {} - {}", segment.index(), segment.url(), error);
            }
            eprintln!();
            eprintln!("❌ 由于无法保证视频完整性，停止下载该 m3u8 播放列表。");
            
            return Err(DownloadError::Io(format!("{} 个 TS 文件经过 {} 次重试后仍然失败，停止下载该 m3u8", failed_count, self.config.retry_count)));
        }
        
        self.progress_reporter.finish_total("✅ 所有分片下载完成!").await;
        
        // 更新固定显示信息
        self.progress_reporter.set_current_download(
            &format!("{total} 个分片"), 
            "流水线下载完成，准备合并"
        ).await;
        
        // 按照索引排序确保正确顺序
        let mut downloaded_files: Vec<_> = results_guard.iter()
            .map(|(index, path)| (*index, path.clone()))
            .collect();
        downloaded_files.sort_by_key(|(index, _)| *index);
        let downloaded_files: Vec<PathBuf> = downloaded_files.into_iter()
            .map(|(_, path)| path)
            .collect();
        
        Ok(downloaded_files)
    }
    
    /// 合并分片为目标文件
    async fn merge_segments_to_mp4(&self, segment_files: Vec<PathBuf>, output_path: &str) -> DownloadResult<()> {
        if segment_files.is_empty() {
            return Err(DownloadError::Io("没有可合并的分片文件".to_string()));
        }

        println!();
        println!("🔧 正在合并 {} 个 TS 分片到文件: {}...", segment_files.len(), output_path);
        
        let mut converter = ConverterFactory::create_ts_converter(self.config.buffer_size);
        
        self.progress_reporter.start_total_progress(segment_files.len() as u64, "合并中...").await;
        
        // 读取所有 TS 文件并添加到转换器
        for segment_file in segment_files {
            let mut file = File::open(&segment_file).await?;
            let mut buffer = Vec::new();
            file.read_to_end(&mut buffer).await?;
            
            converter.add_data(&buffer);
            self.progress_reporter.increment_total(1).await;
        }
        
        self.progress_reporter.finish_total("✅ 数据读取完成!").await;
        
        // 合并为 TS 文件
        println!("🎯 正在生成最终 TS 文件...");
        let output_path = Path::new(output_path);
        converter.convert_to_file(output_path).await?;
        
        Ok(())
    }
    
    // 已移除不必要的格式检测逻辑，保持原有下载逻辑
}

#[async_trait]
impl Downloader for DualProgressHttpDownloader {
    async fn download(&self, url: &str, output_path: &str) -> DownloadResult<()> {
        // 下载播放列表
        let playlist = self.download_playlist(url).await?;
        
        // 下载所有分片
        let segment_files = self.download_all_segments(playlist.as_ref()).await?;
        
        // 合并为 TS 文件
        self.merge_segments_to_mp4(segment_files, output_path).await?;
        
        // 清理临时文件（但保留输出文件）
        self.cleanup_except_output(output_path).await?;
        
        Ok(())
    }
    
    async fn download_playlist(&self, url: &str) -> DownloadResult<Box<dyn Playlist<SegmentType = crate::playlist::M3u8Segment>>> {
        // 设置固定的"正在下载"显示
        self.progress_reporter.set_current_download(url, "下载播放列表中").await;
        
        let response = self.client.get(url).send().await?;
        let content = response.text().await?;
        let base_url = Url::parse(url)?;
        
        // 检查是否为嵌套的播放列表（包含其他m3u8链接）
        if self.is_nested_playlist(&content) {
            // 解析嵌套播放列表，获取实际的TS分片URL
            return self.parse_nested_playlist(&content, &base_url).await;
        }
        
        // 创建正确的基础URL：移除文件名但保留路径
        let base_path = url_path_without_filename(base_url.path());
        let mut corrected_base_url = base_url.clone();
        corrected_base_url.set_path(&base_path);
        
        PlaylistFactory::create_playlist(&content, corrected_base_url)
    }
    
    async fn cleanup(&self) -> DownloadResult<()> {
        if self.config.temp_dir.exists() {
            fs::remove_dir_all(&self.config.temp_dir).await?;
            println!("🧹 已清理临时文件");
        }
        Ok(())
    }
}

impl DualProgressHttpDownloader {
    /// 清理临时文件，但保留输出文件
    async fn cleanup_except_output(&self, output_path: &str) -> DownloadResult<()> {
        if self.config.temp_dir.exists() {
            // 获取输出文件的绝对路径
            let output_path_obj = Path::new(output_path).canonicalize().unwrap_or(Path::new(output_path).to_path_buf());
            let output_file_name = output_path_obj.file_name();
            
            // 检查输出文件是否在临时目录中
            let output_in_temp_dir = output_path_obj.starts_with(&self.config.temp_dir);
            
            if output_in_temp_dir {
                // 如果输出文件在临时目录中，只删除其他文件
                let mut entries = fs::read_dir(&self.config.temp_dir).await?;
                while let Some(entry) = entries.next_entry().await? {
                    let path = entry.path();
                    
                    // 如果不是输出文件，则删除
                    if let Some(file_name) = path.file_name() {
                        if Some(file_name) != output_file_name {
                            if path.is_dir() {
                                fs::remove_dir_all(&path).await?;
                            } else {
                                fs::remove_file(&path).await?;
                            }
                        }
                    } else {
                        // 如果没有文件名，直接删除
                        if path.is_dir() {
                            fs::remove_dir_all(&path).await?;
                        } else {
                            fs::remove_file(&path).await?;
                        }
                    }
                }
                
                // 检查临时目录是否为空或只包含输出文件，如果是则删除目录本身
                let mut dir_entries = fs::read_dir(&self.config.temp_dir).await?;
                let mut only_output_file_exists = true;
                while let Some(entry) = dir_entries.next_entry().await? {
                    let path = entry.path();
                    if let Some(file_name) = path.file_name() {
                        if Some(file_name) != output_file_name {
                            only_output_file_exists = false;
                            break;
                        }
                    } else {
                        // 有其他条目（可能是目录），不删除
                        only_output_file_exists = false;
                        break;
                    }
                }
                
                // 如果目录中只剩下输出文件或为空，则删除整个目录
                if only_output_file_exists {
                    fs::remove_dir_all(&self.config.temp_dir).await?;
                }
            } else {
                // 如果输出文件不在临时目录中，可以安全地删除整个临时目录
                fs::remove_dir_all(&self.config.temp_dir).await?;
            }
            
            println!("🧹 已清理临时文件（保留输出文件）");
        }
        Ok(())
    }
    
    /// 检查是否为嵌套播放列表
    fn is_nested_playlist(&self, content: &str) -> bool {
        // 如果内容中包含其他m3u8文件的引用，则为嵌套播放列表
        content.lines().any(|line| {
            !line.starts_with("#") && !line.is_empty() && line.contains(".m3u8")
        })
    }
    
    /// 解析嵌套播放列表，获取实际的TS分片
    async fn parse_nested_playlist(&self, content: &str, base_url: &Url) -> DownloadResult<Box<dyn Playlist<SegmentType = crate::playlist::M3u8Segment>>> {
        // 查找第一个非注释行中的m3u8 URL
        for line in content.lines() {
            if !line.starts_with("#") && !line.is_empty() && line.contains(".m3u8") {
                // 解析嵌套的m3u8 URL
                let nested_url = base_url.join(line)?;
                println!("🔗 检测到嵌套播放列表，正在解析: {}", nested_url);
                
                // 下载嵌套的播放列表
                let nested_response = self.client.get(nested_url.as_str()).send().await?;
                let nested_content = nested_response.text().await?;
                
                // 使用嵌套播放列表的URL作为基础URL
                let nested_base_path = url_path_without_filename(nested_url.path());
                let mut nested_base_url = nested_url.clone();
                nested_base_url.set_path(&nested_base_path);
                
                // 解析嵌套播放列表中的实际TS分片
                return PlaylistFactory::create_playlist(&nested_content, nested_base_url);
            }
        }
        
        // 如果没有找到嵌套的m3u8，返回错误
        Err(DownloadError::InvalidM3u8)
    }
}

/// HTTP 下载器实现（单层进度条，向后兼容）
pub struct HttpDownloader {
    client: Client,
    config: DownloadConfig,
    progress_reporter: Arc<dyn ProgressReporter>,
    retry_strategy: RetryStrategy,
}

impl HttpDownloader {
    pub fn new(
        config: DownloadConfig,
        progress_reporter: Arc<dyn ProgressReporter>,
        retry_strategy: RetryStrategy,
    ) -> DownloadResult<Self> {
        let client = Self::create_http_client(&config)?;
        
        if let Some(ref proxy) = config.proxy_url {
            println!("🔴 已启用 SOCKS5 代理: {proxy}");
        }
        
        Ok(Self {
            client,
            config,
            progress_reporter,
            retry_strategy,
        })
    }
    
    fn create_http_client(config: &DownloadConfig) -> DownloadResult<Client> {
        let mut client_builder = Client::builder()
            .timeout(Duration::from_secs(config.timeout_secs));
        
        // 如果提供了代理地址，则配置代理
        if let Some(ref proxy) = config.proxy_url {
            let proxy_config = reqwest::Proxy::all(proxy)
                .map_err(|e| DownloadError::Network(e.to_string()))?;
            client_builder = client_builder.proxy(proxy_config);
        }
        
        client_builder
            .build()
            .map_err(|e| DownloadError::Network(e.to_string()))
    }
    
    /// 下载单个分片（静态方法，用于并发调用）
    async fn download_segment_with_strategy(
        client: &Client,
        retry_strategy: &RetryStrategy,
        temp_dir: &Path,
        buffer_size: usize,
        segment: &crate::playlist::M3u8Segment,
    ) -> DownloadResult<PathBuf> {
        let detector = FormatDetector::new();
        let format = detector.detect_format(segment.url()).unwrap_or_else(|| detector.default_format());
        let filename = format.generate_filename(segment.index());
        let filepath = temp_dir.join(&filename);
        
        // 如果文件已存在，直接返回
        if filepath.exists() {
            return Ok(filepath);
        }
        
        let url = segment.url();
        let filepath_clone = filepath.clone();
        
        retry_strategy.execute(|| async {
            let response = client.get(url).send().await?;
            
            // 检查 HTTP 状态码
            if !response.status().is_success() {
                return Err(DownloadError::Network(format!("HTTP 错误: {}", response.status())));
            }
            
            let mut stream = response.bytes_stream();
            let file = File::create(&filepath_clone).await?;
            let mut writer = BufWriter::with_capacity(buffer_size, file);
            
            // 零拷贝流式下载
            while let Some(chunk_result) = stream.next().await {
                let chunk = chunk_result?;
                writer.write_all(&chunk).await?;
            }
            
            writer.flush().await?;
            
            // 验证文件大小（简单检查）
            let metadata = fs::metadata(&filepath_clone).await?;
            if metadata.len() == 0 {
                fs::remove_file(&filepath_clone).await.ok(); // 删除空文件
                return Err(DownloadError::Io("下载的文件为空".to_string()));
            }
            
            Ok(())
        }).await?;
        
        Ok(filepath)
    }
    
    /// 并发下载所有分片（单层进度条）
    async fn download_all_segments(&self, playlist: &dyn Playlist<SegmentType = crate::playlist::M3u8Segment>) -> DownloadResult<Vec<PathBuf>> {
        ensure_dir_exists(&self.config.temp_dir).await?;
        
        let segments = playlist.segments();
        let total = segments.len();
        
        self.progress_reporter.start(total as u64, "下载中...").await;
        
        let mut downloaded_files = Vec::with_capacity(total);
        let mut current_batch = 0;
        let mut failed_segments = Vec::new();
        
        // 分批并发下载
        while current_batch < total {
            let end_batch = std::cmp::min(current_batch + self.config.concurrent, total);
            let batch = &segments[current_batch..end_batch];
            
            let mut handles = Vec::new();
            
            // 为每个 TS 文件创建一个 tokio 协程
            for segment in batch {
                let client = self.client.clone();
                let retry_strategy = self.retry_strategy.clone();
                let temp_dir = self.config.temp_dir.clone();
                let buffer_size = self.config.buffer_size;
                let segment_clone = segment.clone();
                let progress_reporter = Arc::clone(&self.progress_reporter);
                
                let handle = tokio::spawn(async move {
                    let result = Self::download_segment_with_strategy(
                        &client, 
                        &retry_strategy, 
                        &temp_dir, 
                        buffer_size, 
                        &segment_clone
                    ).await;
                    progress_reporter.increment(1).await;
                    (segment_clone, result)
                });
                
                handles.push(handle);
            }
            
            // 等待当前批次的所有下载完成
            for handle in handles {
                let (segment, result) = handle.await
                    .map_err(|e| DownloadError::Io(e.to_string()))?;
                
                match result {
                    Ok(filepath) => {
                        downloaded_files.push(filepath);
                    }
                    Err(e) => {
                        failed_segments.push((segment, e));
                    }
                }
            }
            
            current_batch = end_batch;
        }
        
        // 检查是否有失败的下载
        if !failed_segments.is_empty() {
            let failed_count = failed_segments.len();
            self.progress_reporter.finish("❌ 部分文件下载失败").await;
            
            eprintln!();
            eprintln!("❌ 以下 {} 个 TS 文件经过 {} 次重试后仍然失败：", failed_count, self.config.retry_count);
            for (segment, error) in &failed_segments {
                eprintln!("  - 索引 {}: {} - {}", segment.index(), segment.url(), error);
            }
            eprintln!();
            eprintln!("❌ 由于无法保证视频完整性，停止下载该 m3u8 播放列表。");
            
            return Err(DownloadError::Io(format!("{} 个 TS 文件经过 {} 次重试后仍然失败，停止下载该 m3u8", failed_count, self.config.retry_count)));
        }
        
        self.progress_reporter.finish("✅ 下载完成!").await;
        
        // 按照索引排序确保正确顺序
        downloaded_files.sort_by(|a, b| {
            let a_name = a.file_name().unwrap().to_str().unwrap();
            let b_name = b.file_name().unwrap().to_str().unwrap();
            a_name.cmp(b_name)
        });
        
        Ok(downloaded_files)
    }
    
    /// 合并分片为 MP4（单层进度条）
    async fn merge_segments_to_mp4(&self, segment_files: Vec<PathBuf>, _output_path: &str) -> DownloadResult<()> {
        // 移除了正在处理分片的输出
        // println!("🔧 正在处理 {} 个 TS 分片到 MP4: {}...", segment_files.len(), output_path);
        
        // 暂时注释掉converter相关代码
        // let mut converter = ConverterFactory::create_mp4_converter(self.config.buffer_size);
        
        self.progress_reporter.start(segment_files.len() as u64, "处理中...").await;
        
        // 暂时简化处理：只统计数量
        for _segment_file in segment_files {
            self.progress_reporter.increment(1).await;
        }
        
        self.progress_reporter.finish("✅ 数据处理完成!").await;
        
        Ok(())
    }
}

#[async_trait]
impl Downloader for HttpDownloader {
    async fn download(&self, url: &str, output_path: &str) -> DownloadResult<()> {
        // 下载播放列表
        let playlist = self.download_playlist(url).await?;
        
        // 下载所有分片
        let segment_files = self.download_all_segments(playlist.as_ref()).await?;
        
        // 转换并合并为 MP4
        self.merge_segments_to_mp4(segment_files, output_path).await?;
        
        // 清理临时文件
        self.cleanup().await?;
        
        Ok(())
    }
    
    async fn download_playlist(&self, url: &str) -> DownloadResult<Box<dyn Playlist<SegmentType = crate::playlist::M3u8Segment>>> {
        // 显示固定的下载信息（对于单层进度条，使用println保持兼容）
        println!("📥 正在下载播放列表: {url}");
        
        let response = self.client.get(url).send().await?;
        let content = response.text().await?;
        let base_url = Url::parse(url)?;
        // 创建正确的基础URL：移除文件名但保留路径
        let base_path = url_path_without_filename(base_url.path());
        let mut corrected_base_url = base_url.clone();
        corrected_base_url.set_path(&base_path);
        
        PlaylistFactory::create_playlist(&content, corrected_base_url)
    }
    
    async fn cleanup(&self) -> DownloadResult<()> {
        if self.config.temp_dir.exists() {
            fs::remove_dir_all(&self.config.temp_dir).await?;
            println!("🧹 已清理临时文件");
        }
        Ok(())
    }
}

/// 下载器工厂
pub struct DownloaderFactory;

impl DownloaderFactory {
    /// 创建双层进度条下载器
    pub fn create_dual_progress_downloader(
        config: DownloadConfig,
        progress_reporter: Arc<dyn DualProgressReporter>,
        retry_strategy: RetryStrategy,
    ) -> DownloadResult<Arc<dyn Downloader>> {
        let downloader = DualProgressHttpDownloader::new(config, progress_reporter, retry_strategy)?;
        Ok(Arc::new(downloader))
    }
    
    /// 创建单层进度条下载器（向后兼容）
    pub fn create_http_downloader(
        config: DownloadConfig,
        progress_reporter: Arc<dyn ProgressReporter>,
        retry_strategy: RetryStrategy,
    ) -> DownloadResult<Arc<dyn Downloader>> {
        let downloader = HttpDownloader::new(config, progress_reporter, retry_strategy)?;
        Ok(Arc::new(downloader))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_url_path_without_filename() {
        // 测试基本情况
        assert_eq!(url_path_without_filename("/path/to/file.m3u8"), "/path/to/");
        assert_eq!(url_path_without_filename("/path/to/"), "/path/to/");
        assert_eq!(url_path_without_filename("/file.m3u8"), "/");
        assert_eq!(url_path_without_filename("/"), "/");
        assert_eq!(url_path_without_filename("file.m3u8"), "/");
        
        // 测试复杂路径
        assert_eq!(url_path_without_filename("/a/b/c/d/video.m3u8"), "/a/b/c/d/");
        assert_eq!(url_path_without_filename("/80578501-ee80-4633-9c30-acbae2cf2f76/720p/video.m3u8"), "/80578501-ee80-4633-9c30-acbae2cf2f76/720p/");
    }
}